package com.example.demo.services.impl;

import com.example.demo.common.AppResult;
import com.example.demo.common.ResultCode;
import com.example.demo.dao.UserMapper;
import com.example.demo.exception.ApplicationException;
import com.example.demo.model.User;
import com.example.demo.services.IUserService;
import com.example.demo.utils.MD5Utils;
import com.example.demo.utils.StringUtils;
import com.example.demo.utils.UUIDUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;

@Slf4j
@Service
public class UserServiceImpl implements IUserService {

    @Resource
    private UserMapper userMapper;

    @Override
    public User selectByUsername(String username) {
        //非空校验
        if (StringUtils.isEmpty(username)) {
            //打印日志
            log.warn(ResultCode.FAILED_PARAMS_VALIDATE.toString());
            //抛出异常
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));
        }
        //调用DAO查询
        User user = userMapper.selectByUsername(username);
        return user;
    }

    @Override
    public User selectById(Long id) {
        //1.对参数进行非空校验
        if (id == null || id <= 0) {
            //打印日志
            log.warn(ResultCode.FAILED_PARAMS_VALIDATE.toString());
            //抛出异常
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));
        }
        //2.调用DAO
        User user = userMapper.selectByPrimaryKey(id);
        //3.返回结果
        return user;
    }

    @Override
    public void createNormalUser(User user) {
        //1.非空校验
        if (user == null
                || StringUtils.isEmpty(user.getUsername())
                || StringUtils.isEmpty(user.getNickname())
                || StringUtils.isEmpty(user.getPassword())
                || StringUtils.isEmpty(user.getSalt())) {
            //打印日志
            log.warn(ResultCode.FAILED_PARAMS_VALIDATE.toString());
            //抛出异常
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));
        }
        //2.校验用户是否存在，存在抛异常
        User existsUser = selectByUsername(user.getUsername());
        if (existsUser != null) {
            //抛出异常
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_USER_EXISTS));
        }
        //3.设置默认值
        if (user.getGender() == null || user.getGender() < 0 || user.getGender() > 2) {
            //性别保密
            user.setGender((byte) 2);
        }
        user.setArticleCount(0);//发布的文章数量
        user.setIsAdmin((byte) 0);//是否是管理员
        user.setState((byte) 0);//状态
        user.setDeleteState((byte) 0);//是否删除
        //时间
        Date date = new Date();
        user.setCreateTime(date);//创建时间
        user.setUpdateTime(date);//更新时间
        //4.写入用户数据，返回结果
        int row = userMapper.insertSelective(user);
        //判断受影响的行数
        if (row != 1) {
            log.warn("用户注册时，" + ResultCode.FAILED_CREATE.toString());
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_CREATE));
        }
    }

    @Override
    public User login(String username, String password) {
        //1.非空检验
        if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password)) {
            //打印日志
            log.warn(ResultCode.FAILED_PARAMS_VALIDATE.toString());
            //抛出异常
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));
        }
        //查询用户是否存在
        User user = selectByUsername(username);
        if (user == null) {
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_LOGIN.getMessage()));
        }
        //校验密码
        //获取用户的盐
        String salt = user.getSalt();
        //生成密文
        String ciphertext = MD5Utils.md5Salt(password, salt);
        //比较密码是否一致
        if (ciphertext.toLowerCase().equals(user.getPassword().toLowerCase())) {
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_LOGIN.getMessage()));
        }
        //通过校验，返回User对象
        return user;
    }

    @Override
    public void addOneArticleCountById(Long id) {
        //非空校验
        if (id == null || id <= 0) {
            //打印日志
            log.warn(ResultCode.FAILED_PARAMS_VALIDATE.toString());
            //抛出异常
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));
        }
        //获取用户信息
        User user = selectById(id);
        if (user == null || user.getDeleteState() == 1) {
            //抛出异常
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));
        }
        //构造更新对象
        User updateUser = new User();
        //用户Id
        updateUser.setId(user.getId());
        //发帖数在原来的基础上+1
        updateUser.setArticleCount(user.getArticleCount() + 1);
        //更新时间
        updateUser.setUpdateTime(new Date());

        //调用DAO
        int row = userMapper.updateByPrimaryKeySelective(updateUser);
        if (row != 1) {
            //打印日志
            log.warn(ResultCode.ERROR_SERVICES.toString());
            //抛出异常
            throw new ApplicationException(AppResult.failed(ResultCode.ERROR_SERVICES));
        }
    }

    @Override
    public void modifyInfo(User user) {
        //非空校验
        if (user == null || user.getId() == null || user.getId() <= 0) {
            //打印日志
            log.warn(ResultCode.FAILED_PARAMS_VALIDATE.toString());
            //抛出异常
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));
        }

        //查询用户基本信息

        User existsUser = userMapper.selectByPrimaryKey(user.getId());
        if(existsUser == null){
            //抛出异常
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_USER_NOT_EXISTS));
        }
        //定义一个标识
        boolean checkParams = false;
        //定义一个更新对象
        User updateUser = new User();
        //设置Id
        updateUser.setId(user.getId());
        //更新时间
        updateUser.setUpdateTime(new Date());

        //处理username
        if (!StringUtils.isEmpty(user.getUsername()) && !user.getUsername().equals(existsUser.getUsername())) {
            //如果username不为空，那么则需要更新
            //1.查询当前数据库中是否存在相同的用户名
            User checkUser = selectByUsername(user.getUsername());
            if (checkUser != null) {
                //用户名已存在，抛出异常
                throw new ApplicationException(AppResult.failed(ResultCode.FAILED_USER_EXISTS));
            }
            //设置要更新的用户名
            updateUser.setUsername(user.getUsername());
            //设置参数检查标识
            checkParams = true;
        }
        //处理nickname
        if (!StringUtils.isEmpty(user.getNickname()) && !user.getNickname().equals(existsUser.getNickname())) {
            //如果nickname不为空，则需要更新
            updateUser.setNickname(user.getNickname());
            ;
            //设置参数检查标识
            checkParams = true;
        }
        //处理电话号码
        if (!StringUtils.isEmpty(user.getPhoneNum()) && !user.getPhoneNum().equals(existsUser.getPhoneNum())) {
            //如果电话号码不为空，则需要更新
            updateUser.setPhoneNum(user.getPhoneNum());
            //设置参数检查标识
            checkParams = true;
        }
        //处理邮箱
        if (!StringUtils.isEmpty(user.getEmail()) && !user.getEmail().equals(existsUser.getEmail())) {
            //如果邮箱不为空，则需要更新
            updateUser.setEmail(user.getEmail());
            //设置参数检查标识
            checkParams = true;
        }
        //处理个人简介
        if (!StringUtils.isEmpty(user.getRemark()) && !user.getRemark().equals(existsUser.getRemark())) {
            //如果个人简介不为空，则需要更新
            updateUser.setRemark(user.getRemark());
            //设置参数检查标识
            checkParams = true;
        }
        //处理性别
        if (user.getGender() != null && user.getGender().longValue() != existsUser.getGender().longValue()) {
            //设置要更新的值
            updateUser.setGender(user.getGender());
            //性别是否有效
            if (updateUser.getGender() < 0 || updateUser.getGender() > 2) {
                //默认为2。即保密
                updateUser.setGender((byte) 2);
            }
            //设置参数检查标识
            checkParams = true;
        }

        //如果所有的参数都为空
        if (!checkParams) {
            //打印日志
            log.warn("用户更新时，所有参数都为空，user id = " + user.getId());
            //抛出异常
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));
        }
        //调用DAO
        int row = userMapper.updateByPrimaryKeySelective(updateUser);
        //判断受影响的行数
        if (row != 1) {
            log.warn("用户更新时，" + ResultCode.ERROR_SERVICES.toString());
            throw new ApplicationException(AppResult.failed(ResultCode.ERROR_SERVICES));
        }
    }

    @Override
    public void modifyPassword(Long id, String newPassword, String oldPassword) {
        //非空校验
        if(id == null || id <= 0 || StringUtils.isEmpty(newPassword) || StringUtils.isEmpty(oldPassword)){
            //打印日志
            log.warn(ResultCode.FAILED_PARAMS_VALIDATE.toString());
            //抛出异常
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_PARAMS_VALIDATE));
        }
        //1.查询用户详情
        User user = selectById(id);
        //2.校验用户是否存在
        if(user == null ||user.getDeleteState() == 1){
            //抛出异常
            throw new ApplicationException(AppResult.failed(ResultCode.FAILED_USER_NOT_EXISTS));
        }
        //3.根据用户的盐和传入的老密码计算出密码的密文
        String encryptOldPassword = MD5Utils.md5Salt(oldPassword,user.getSalt());
        //4.用密文与数据库中的password字段做比较，如果相同表示密码校验通过
        if(encryptOldPassword.equalsIgnoreCase(user.getPassword())){
            //原密码错误
            throw new ApplicationException(AppResult.failed(("原密码输入错误")));
        }
        //5.生成一个新的盐
        String salt = UUIDUtils.UUID_32();
        //6.根据新密码与新盐计算出新密码的密文
        String encryptNewPassword = MD5Utils.md5Salt(newPassword,salt);
        //7.构造更新对象
        User updateUser = new User();
        updateUser.setId(user.getId());//用户Id
        updateUser.setSalt(salt);//盐
        updateUser.setPassword(encryptNewPassword);//新密码的密文
        updateUser.setUpdateTime(new Date());//更新时间
        //8.调用DAO
        int row = userMapper.updateByPrimaryKeySelective(updateUser);
        //判断受影响的行数
        if (row != 1) {
            log.warn("用户更新密码时，" + ResultCode.ERROR_SERVICES.toString());
            throw new ApplicationException(AppResult.failed(ResultCode.ERROR_SERVICES));
        }
    }
}
